/*
 *  Copyright 1999-2021 Seata.io Group.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.diy.sigmund.diyorder.service.impl;

import com.diy.sigmund.diycommon.entity.ResultMsg;
import com.diy.sigmund.diycommon.entity.base.exception.DiyRuntimeException;
import com.diy.sigmund.diycommon.entity.enumerate.ResponseEnum;
import com.diy.sigmund.diycommon.util.seq.SeqUtil;
import com.diy.sigmund.diycommon.util.time.DateUtil;
import com.diy.sigmund.diyorder.entity.po.OdSeckillOrder;
import com.diy.sigmund.diyorder.feign.client.SeataUserClient;
import com.diy.sigmund.diyorder.mapper.OdSeckillCommodityMapper;
import com.diy.sigmund.diyorder.mapper.OdSeckillOrderMapper;
import com.diy.sigmund.diyorder.service.SeataOrderService;
import io.seata.spring.annotation.GlobalLock;
import io.seata.spring.annotation.GlobalTransactional;
import java.math.BigDecimal;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author IT云清
 */
@Service("orderServiceImpl")
public class SeataOrderServiceImpl implements SeataOrderService {

    private static final Logger log = LoggerFactory.getLogger(SeataOrderServiceImpl.class);

    @Autowired
    private OdSeckillOrderMapper odSeckillOrderMapper;
    @Autowired
    private OdSeckillCommodityMapper odSeckillCommodityMapper;
    @Autowired
    private SeataUserClient seataUserClient;

    /**
     * 创建订单
     *
     * @param order
     * @return 测试结果：
     * 1.添加本地事务：仅仅扣减库存
     * 2.不添加本地事务：创建订单，扣减库存
     */
    @Override
    @GlobalLock
    @GlobalTransactional(name = "fsp-create-order", rollbackFor = Exception.class)
    public ResultMsg create(OdSeckillOrder order) {
        log.info("------->交易开始");
        //本地方法
        order.setId(SeqUtil.snowflakeId());
        order.setRecordStatus("0");
        order.setPhone("18700001111");
        order.setCommodityId("1001");
        order.setTransactionQuantity(1);
        order.setTransactionAmount(new BigDecimal("6000"));
        order.setOrderStatus("1");
        odSeckillOrderMapper.insertSelective(order);

        //远程方法 扣减库存
        ResultMsg resultMsg = seataUserClient.decreaseInventory(order.getCommodityId(), order.getTransactionQuantity());
        log.info("扣减库存结束:{}", resultMsg);

        //远程方法 扣减账户余额
        log.info("------->扣减账户开始order中");
        ResultMsg resultMsg1 = seataUserClient.decreaseAccount(order.getPhone(), order.getTransactionAmount());
        log.info("------->扣减账户结束order中:{}", resultMsg1);
        if (resultMsg1.unSuccess()){
            throw new DiyRuntimeException(ResponseEnum.INTERNAL_SERVER_ERROR);
        }
        // if (new Date().after(DateUtil.parseStrToDate("2018",DateUtil.DATE_FORMAT_YYYY))){
        //     throw new DiyRuntimeException(ResponseEnum.INTERNAL_SERVER_BUSY);
        // }

        log.info("------->交易结束");
        return ResultMsg.success("Create order success");
    }

    /**
     * 修改订单状态
     */
    @Override
    public ResultMsg update(String orderId, String orderStatus) {
        log.info("修改订单状态，入参为：orderId={},orderStatus={}", orderId, orderStatus);
        OdSeckillOrder odSeckillOrder = new OdSeckillOrder();
        odSeckillOrder.setId(orderId);
        odSeckillOrder.setOrderStatus(orderStatus);
        int i = odSeckillOrderMapper.updateByPrimaryKeySelective(odSeckillOrder);

        return i == 1 ? ResultMsg.success("订单状态修改成功") : ResultMsg.fail("订单状态修改失败");
    }

    @Override
    public ResultMsg decreaseInventory(String commodityId, Integer transactionQuantity) {
        log.info("扣减库存订单commodityId:{},transactionQuantity:{}", commodityId, transactionQuantity);
        odSeckillCommodityMapper.decrOneInventory(commodityId, transactionQuantity);
        return ResultMsg.success("扣减库存成功");
    }
}
